# coding=UTF-8
import os

from service import data_service
from service.data_service import macd_dict
from utils import doc_util, json_util, k_util, date_util, read_config

# 缓存最近用到的
macd_cache_dict = {}


def init_calculate_macd(code):
    print(code + "重新计算macd")
    global macd_dict
    MACD_list = []
    name = data_service.stock(code)['name']
    exchange = data_service.stock(code)['exchange']
    day_k_result = k_util.day_k_size(code, name, exchange, 12000)
    day_k_result = k_util.format_k_lines(day_k_result)
    day_k_result.reverse()
    length = len(day_k_result)
    if length == 0:
        return MACD_list
    EMA12 = float(json_util.info_to_json(day_k_result[0])['sp'])
    EMA26 = float(json_util.info_to_json(day_k_result[0])['sp'])
    DEA = 0
    for num in range(1, length):
        sp = float(json_util.info_to_json(day_k_result[num])['sp'])
        rq = json_util.info_to_json(day_k_result[num])['rq']
        # < 1 > 计算12日和26日移动平均线EMA1和EMA2
        # 当日EMA(12) = 前一日EMA(12)×11 / 13＋当日收盘价×2 / 13
        # 当日EMA(26) = 前一日EMA(26)×25 / 27＋当日收盘价×2 / 27
        EMA12 = EMA12 + (sp - EMA12) * 2 / 13
        EMA26 = EMA26 + (sp - EMA26) * 2 / 27
        # < 2 > 计算离差值(DIFF)
        # DIFF = 当日EMA(12)－当日EMA(26)
        diff = EMA12 - EMA26
        # <3>计算9日离差平均值DEA
        # 当日DEA=前一日DEA×8/10＋当日DIFF×2/10
        DEA = DEA * 0.8 + diff * 0.2
        # < 4 > 计算MACD
        # MACD = 2×(DIFF－DEA)
        MACD = 2 * (diff - DEA)
        macd_info = {'rq': rq, 'macd': MACD, 'EMA12': EMA12, 'EMA26': EMA26, 'DEA': DEA}
        MACD_list.append(macd_info)
    # 持久化到本地
    record_size = 100
    macd_len = len(MACD_list)
    # 持久化到本地macd
    update_doc_macd_dict(code, MACD_list)
    if 100 > macd_len:
        record_size = macd_len
    macd_dict[code] = MACD_list[macd_len - record_size]
    # 更新macd字典
    update_macd_dict(macd_dict)


# 获取 macd 最多支持天数100天 突破100天限制
# start_rq : 开始日期 格式'2020-11-02' 倒序
# size   : 开始日期往前几天（负数往后推）
def get_macd_interval(code, start_rq, size):
    # 获取k线
    global macd_dict
    MACD_list = []
    result_macd_list = []
    if code not in macd_dict.keys():
        init_calculate_macd(code)
    if code in macd_dict.keys():
        macd_info = macd_dict[code]
        macd_rq = macd_info['rq']
        # 时间比较
        compare_flag = date_util.compare_date_str(macd_rq, start_rq)
        if compare_flag == 1:
            print(code + 'macd_rq不满足start_rq' + start_rq + '需求重新获取')
            result = doc_util.get_doc_info_null(os.path.join(read_config.data_path, 'common', 'macd', code))
            init_flag = 0
            if len(result) != 0:
                for i in range(len(result)):
                    macd_info = json_util.info_to_json(result[i])
                    m_rq = macd_info['rq']
                    if (date_util.compare_date_str(m_rq, start_rq)) == 0:
                        init_flag = 1
                        for j in range(size):
                            MACD_list.append(json_util.info_to_json(result[i - j]))
                        return MACD_list
            if init_flag == 0:
                init_calculate_macd(code)
            macd_info = macd_dict[code]
            macd_rq = macd_info['rq']
        EMA12 = macd_info['EMA12']
        EMA26 = macd_info['EMA26']
        DEA = macd_info['DEA']
        day_k_result = k_util.day_k_local_frequency(code, 120, 3600)
        day_k_result.reverse()
        begin_flag = 0
        count = 0
        for day_k in day_k_result:
            day_k = json_util.info_to_json(day_k)
            rq = day_k['rq']
            if begin_flag == 0:
                if rq == macd_rq:
                    begin_flag = 1
                    continue
                else:
                    continue
            count += 1
            sp = float(day_k['sp'])
            # < 1 > 计算12日和26日移动平均线EMA1和EMA2
            # 当日EMA(12) = 前一日EMA(12)×11 / 13＋当日收盘价×2 / 13
            # 当日EMA(26) = 前一日EMA(26)×25 / 27＋当日收盘价×2 / 27
            EMA12 = EMA12 + (sp - EMA12) * 2 / 13
            EMA26 = EMA26 + (sp - EMA26) * 2 / 27
            # < 2 > 计算离差值(DIFF)
            # DIFF = 当日EMA(12)－当日EMA(26)
            diff = EMA12 - EMA26
            # <3>计算9日离差平均值DEA
            # 当日DEA=前一日DEA×8/10＋当日DIFF×2/10
            DEA = DEA * 0.8 + diff * 0.2
            # < 4 > 计算MACD
            # MACD = 2×(DIFF－DEA)
            MACD = 2 * (diff - DEA)
            macd_info = {'rq': rq, 'macd': MACD, 'EMA12': EMA12, 'EMA26': EMA26, 'DEA': DEA}
            MACD_list.append(macd_info)
        if begin_flag == 1:
            # 更新macd_dict字典
            update_macd_dict(macd_dict)
        if begin_flag == 0 or count < size:
            print("code" + code + "#############报警需要重新更新macd")
            macd_dict.pop(code)
            get_macd_interval(code, start_rq, size)
    else:
        print("code" + code + "#####未开市没有macd线")
        return result_macd_list
    length = len(MACD_list)
    for count in range(length):
        macd = MACD_list[length - count - 1]
        rq = macd['rq']
        if rq == start_rq:
            if size > length - count:
                size = length - count
            for num in range(size):
                result_macd_list.append(MACD_list[length - count - 1 - num])
            break
    # 更新持久化文件
    record_size = 100
    if 100 > len(MACD_list):
        record_size = len(MACD_list)
    if len(MACD_list) == 0:
        return result_macd_list
    diff_days = date_util.diff_days_str(macd_dict[code]['rq'], MACD_list[length - record_size]['rq'])
    if diff_days > 14:
        macd_dict[code] = MACD_list[length - record_size]
        update_macd_dict(macd_dict)
    return result_macd_list


# 获取带有缓存的macd列表
# macd_list_dict['all'] = macd_list_all
# macd_list_dict['result'] = macd_list_result
def get_macd_list_cache(macd_list_all, code, start_rq, size):
    # 获取k线
    global macd_dict
    macd_list_dict = {}
    if len(macd_list_all) == 0:
        macd_list_all = doc_util.get_doc_info_null(os.path.join(read_config.data_path, 'common', 'macd', code))
        if len(macd_list_all) == 0:
            init_calculate_macd(code)
            macd_list_all = doc_util.get_doc_info_null(os.path.join(read_config.data_path, 'common', 'macd', code))
        rq = json_util.info_to_json(macd_list_all[len(macd_list_all) - 1])['rq']
        if date_util.diff_days_str(rq, date_util.get_date_str()) > 0:
            dif_days = date_util.diff_days_str(rq, date_util.get_date_str())
            itv_macd_list = get_macd_interval(code, date_util.get_date_str(), dif_days + 1)
            itv_len = len(itv_macd_list)
            add_flag = 0
            for i in range(itv_len):
                if itv_macd_list[itv_len - 1 - i]['rq'] == rq or add_flag == 1:
                    add_flag = 1
                    macd_list_all.append(itv_macd_list[itv_len - 1 - i])
            # 洗数据
            for i in range(len(macd_list_all)):
                macd_list_all[i] = json_util.info_to_json(macd_list_all[i])
            update_doc_macd_dict(code, macd_list_all)
    macd_list_result = []
    for i in range(len(macd_list_all)):
        macd_info = json_util.info_to_json(macd_list_all[i])
        if macd_info['rq'] == start_rq:
            for j in range(size):
                macd_list_result.append(json_util.info_to_json(macd_list_all[i - j]))
            break
    macd_list_dict['all'] = macd_list_all
    macd_list_dict['result'] = macd_list_result
    return macd_list_dict


# 根据前一天 计算下一天的macd
# macd_pre: 前一天的 macd_info
# rq : 当天的日期
# price : 当天的最新价格
def cal_macd_next(macd_pre, rq, price):
    # < 1 > 计算12日和26日移动平均线EMA1和EMA2
    # 当日EMA(12) = 前一日EMA(12)×11 / 13＋当日收盘价×2 / 13
    # 当日EMA(26) = 前一日EMA(26)×25 / 27＋当日收盘价×2 / 27
    EMA12 = macd_pre['EMA12'] + (price - macd_pre['EMA12']) * 2 / 13
    EMA26 = macd_pre['EMA26'] + (price - macd_pre['EMA26']) * 2 / 27
    # < 2 > 计算离差值(DIFF)
    # DIFF = 当日EMA(12)－当日EMA(26)
    diff = EMA12 - EMA26
    # <3>计算9日离差平均值DEA
    # 当日DEA=前一日DEA×8/10＋当日DIFF×2/10
    DEA = macd_pre['DEA'] * 0.8 + diff * 0.2
    # < 4 > 计算MACD
    # MACD = 2×(DIFF－DEA)
    MACD = 2 * (diff - DEA)
    macd_next = {'rq': rq, 'macd': MACD, 'EMA12': EMA12, 'EMA26': EMA26, 'DEA': DEA}
    return macd_next


# 获取当前的macd
# rt_price : 最新价格
# size   : 获取天数
# macd_info = {'rq': rq, 'macd': MACD, 'EMA12': EMA12, 'EMA26': EMA26, 'DEA': DEA}
def get_macd_now(code, size, rt_price):
    return get_macd_with_time(code, size, date_util.get_date_str(), rt_price)


# 获取
# cur_price : 当前价格
# size   : 获取天数
# date_str : 日期
# macd_info = {'rq': rq, 'macd': MACD, 'EMA12': EMA12, 'EMA26': EMA26, 'DEA': DEA}
def get_macd_with_time(code, size, date_str, cur_price):
    # 获取k线
    global macd_cache_dict
    result_list = []
    if code not in macd_cache_dict.keys() or \
            json_util.info_to_json(macd_cache_dict[code][0])['rq'] != date_util.get_date_str():
        macd_list_dict = get_macd_list_cache([], code, date_str, size + 1)
        all_macds = macd_list_dict['all']
        all_macds.reverse()
        macd_cache_dict[code] = all_macds
    MACD_list = macd_cache_dict[code]
    macd_len = len(MACD_list)
    if macd_len < size:
        size = macd_len
    for i in range(macd_len):
        macd_info = json_util.info_to_json(MACD_list[i])
        if macd_info['rq'] == date_str:
            # 计算最新的
            macd_info = json_util.info_to_json(MACD_list[i + 1])
            result_list.append(cal_macd_next(macd_info, date_str, cur_price))
            if size == 1:
                return MACD_list
            result_list.append(macd_info)
            if size == 2:
                return MACD_list
            for j in range(2, size):
                result_list.append(json_util.info_to_json(MACD_list[i + j + 1]))
            return result_list


def update_macd_dict(macd_dict):
    # 更新stock_dict
    for key in macd_dict.keys():
        macd_info = json_util.to_json(macd_dict[key])
        macd_info['code'] = key
    doc_util.gen_a_doc(os.path.join(read_config.data_path, 'common', 'macd'), '000000', macd_dict)


def update_doc_macd_dict(code, MACD_list):
    file_path = os.path.join(read_config.data_path, 'common', 'macd')
    if not os.path.exists(os.path.join(file_path, code)):
        open(os.path.join(file_path, code), mode='w', encoding='utf-8').close()
    doc_util.gen_new_doc(file_path, code, MACD_list)


# 取三条macd判断形态
# macd  负连续往下 -\\ 不考虑和卖出
# macd  负连续往上 -// 买入
# macd  负连上拐  -\/  买入信号
# macd  负连下拐  -/\  卖出
# macd  正连续往下 \\ 不考虑和卖出
# macd  正连续往上 // 持有
# macd  正连上拐  \/  买入信号
# macd  正连下拐  /\  卖出
def macd_form(macd_list):
    if len(macd_list) < 3:
        return ''
    macd0 = float(macd_list[0]['macd'])  # 最新日期
    macd1 = float(macd_list[1]['macd'])
    macd2 = float(macd_list[2]['macd'])
    if macd0 > macd1 and macd1 > macd2:
        return '/'
    if macd0 < macd1 and macd1 < macd2:
        return '\\'
    if macd0 >= macd1 and macd1 <= macd2:
        return 'v'
    if macd0 <= macd1 and macd1 >= macd2:
        return '^'


if __name__ == '__main__':
    macd_list1 = get_macd_interval('600031', '2020-12-23', 10)
    for num in range(len(macd_list1)):
        print(macd_list1[num])
